import axios, { type Method, type AxiosRequestConfig,AxiosError,type AxiosResponse } from "axios";
import router from "@/router";
import {useCounterStore}  from "@/stores/counter";
import { ElMessage  } from 'element-plus'
const counterStore = useCounterStore()
/** 
 * 跳转登录页
 * 携带当前页面路由，以期在登录页面完成登录后返回当前页面
 */
const toLogin = () => {
  window.localStorage.removeItem('d_token')
  router.replace({
    name: 'login',
  });
}

/** 
 * 请求失败后的错误统一处理 
 * @param {Number} status 请求失败的状态码
 */
const errorHandle = (status: number,error:string) => {
  // 状态码判断
  switch (status) {

    case 302: ElMessage.error('接口重定向了！'+ status+error);
      break;
    case 400:
      ElMessage.error("发出的请求有错误，服务器没有进行新建或修改数据的操作==>" + status+error)
      break;
    // 401: 未登录
    // 未登录则跳转登录页面，并携带当前页面的路径
    // 在登录成功后返回当前页面，这一步需要在登录页操作。                
    case 401: //重定向
      ElMessage.error("token:登录失效==>" + status+error)
      toLogin()
    //   storage.remove(store.state.Roles)
    //   storage.get(store.state.Roles)
      break;
    // 403 token过期
    // 清除token并跳转登录页
    case 403:
      ElMessage.error("登录过期,用户得到授权，但是访问是被禁止的==>" + status+error)
      // store.commit('token', null);
      setTimeout(() => {
        router.replace({
          path: '/Login',
        });
      }, 1000);
      break;
    case 404:
      ElMessage.error("网络请求不存在==>" + status+error)
      break;
    case 406:
      ElMessage.error("请求的格式不可得==>" + status+error)
      break;
    case 408: ElMessage.error(" 请求超时！"+error)
      break;
    case 410:
      ElMessage.error("请求的资源被永久删除，且不会再得到的==>" + status+error)
      break;
    case 422:
      ElMessage.error("当创建一个对象时，发生一个验证错误==>" + status+error)
      break;
    case 500:
      ElMessage.error("服务器发生错误，请检查服务器==>" + status+error)
      break;
    case 502:
      ElMessage.error("网关错误==>" + status+error)
      break;
    case 503:
      ElMessage.error("服务不可用，服务器暂时过载或维护==>" + status+error)
      break;
    case 504:
      ElMessage.error("网关超时==>" + status+error)
      break;
    default:
      ElMessage.error("其他错误错误==>" + status+error)
  }
}

// 定义接口
interface PendingType {
  url?: string;
  method?: Method;
  params: any;
  data: any;
  cancel: any;
}
// 取消重复请求
const pending: Array<PendingType> = [];
const CancelToken = axios.CancelToken;

// 移除重复请求
const removePending = (config: AxiosRequestConfig) => {
  for (const key in pending) {
    const item: number = +key;
    const list: PendingType = pending[key];
    // 当前请求在数组中存在时执行函数体
    if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
      // 执行取消操作
      list.cancel('操作太频繁，请稍后再试');
      // 从数组中移除记录
      pending.splice(item, 1);
    }
  }
};
/* 实例化请求配置 */
const instance = axios.create({
  headers: {
    "Content-Type": "application/json;charset=UTF-8",
    // "Access-Control-Allow-Origin-Type": '*'
  },
  // 请求时长
  timeout: 1000 * 30,
  // 请求的base地址 TODO:这块以后根据不同的模块调不同的api
  baseURL: "http://127.0.0.1:8000/",
  //     ? "测试"
  //     : "正式",
  // 表示跨域请求时是否需要使用凭证
  withCredentials: false,
})

/** 
 * 请求拦截器 
 * 每次请求前，如果存在token则在请求头中携带token 
 */
// axios.defaults.withCredentials = false;
instance.interceptors.request.use(
  config => {
    // removePending(config);
    config.cancelToken = new CancelToken((c) => {
      pending.push({ url: config.url, method: (config.method) as any, params: config.params, data: config.data, cancel: c });
    });
    // config.headers['X-CSRFToken'] = cookie.parse(document.cookie).csrftoken;
    // 登录流程控制中，根据本地是否存在token判断用户的登录情况        
    // 但是即使token存在，也有可能token是过期的，所以在每次的请求头中携带token        
    // 后台根据携带的token判断用户的登录情况，并返回给我们对应的状态码        
    // 而后我们可以在响应拦截器中，根据状态码进行一些统一的操作。        
    const token = localStorage.getItem('d_token');
    // console.log(123);
    // console.log(token);
    if (token) {
      config.headers.Authorization = token;
    }
    return config;
  },
  error => {
    ElMessage.error(error.data.error.message);
    return Promise.reject(error.data.error.message);
  }

)

// 响应拦截器
instance.interceptors.response.use(
    (response: AxiosResponse): AxiosResponse => {
      // 2xx 范围内的状态码都会触发该函数。对响数据成功时调用。
      if(response.data.code != 200){
        errorHandle(response.data.code,response.data.error)
        // ElMessage.error(response.data.error)
      }
      return response.data;
    },
    (error: AxiosError): Promise<never> => {
      // 超出 2xx 范围的状态码都会触发该函数。对响应错误时调用。
      console.error('请求错误: ', error);
      return Promise.reject(error);
    }
  );
// 只需要考虑单一职责，这块只封装axios
export default instance
